<template>
  <canvas type="2d" v-if="isUseNewCanvas" class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart"
          @touchmove="touchMove" @touchend="touchEnd">
  </canvas>
  <canvas v-else class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove"
          @touchend="touchEnd">
  </canvas>
</template>

<script>
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';

let ctx;

function wrapTouch (event) {
  for (let i = 0; i < event.touches.length; ++i) {
    const touch = event.touches[i];
    touch.offsetX = touch.x;
    touch.offsetY = touch.y;
  }
  return event;
}

export default {
  props: {
    canvasId: {
      type: String,
      default: () => {
        return 'ec-canvas';
      }
    },
    ec: {
      type: Object
    },
    forceUseOldCanvas: {
      type: Boolean,
      value: false
    }
  },
  data () {
    return {
      $curChart: {},
      toHandleList: [],
      isUseNewCanvas: true
    };
  },
  watch: {
    'ec.option': {
      deep: true,
      handler (val, oldVal) {
        this.setOption(val, true, true);
      }
    }
  },
  onReady: function () {
    if (!this.ec) {
      console.warn(
        '组件需绑定 ec 变量，例：<ec-canvas id="mychart-dom-bar" ' +
        'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>'
      );
      return;
    }
    if (!this.ec.lazyLoad) {
      this.init();
    }
  },
  methods: {
    compareVersion (v1, v2) {
      v1 = v1.split('.');
      v2 = v2.split('.');
      const len = Math.max(v1.length, v2.length);

      while (v1.length < len) {
        v1.push('0');
      }
      while (v2.length < len) {
        v2.push('0');
      }

      for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i]);
        const num2 = parseInt(v2[i]);

        if (num1 > num2) {
          return 1;
        } else if (num1 < num2) {
          return -1;
        }
      }
      return 0;
    },
    init (callback) {
      const version = wx.getSystemInfoSync().SDKVersion;

      let canUseNewCanvas = this.compareVersion(version, '2.9.0') >= 0;
      if (this.forceUseOldCanvas) {
        if (canUseNewCanvas) console.warn('开发者强制使用旧canvas,建议关闭');
        canUseNewCanvas = false;
      }
      this.isUseNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas;
      if (this.isUseNewCanvas) {
        // 2.9.0 可以使用 <canvas type="2d"></canvas>
        this.initByNewWay(callback);
      } else {
        const isValid = this.compareVersion(version, '1.9.91') >= 0;
        if (!isValid) {
          console.error(
            '微信基础库版本过低，需大于等于 1.9.91。' +
            '参见：https://github.com/ecomfe/echarts-for-weixin' +
            '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82'
          );
          return;
        } else {
          console.warn(
            '建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能'
          );
          this.initByOldWay(callback);
        }
      }
    },
    initByOldWay (callback) {
      // 1.9.91 <= version < 2.9.0：原来的方式初始化
      ctx = wx.createCanvasContext(this.canvasId, this);
      const canvas = new WxCanvas(ctx, this.canvasId, false);
      const that = this
      echarts.setCanvasCreator(() => {
        return canvas;
      });
      // const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
      const canvasDpr = 1;
      var query = wx.createSelectorQuery().in(this);
      query
        .select('.ec-canvas')
        .boundingClientRect(res => {
          if (typeof callback === 'function') {
            that.$curChart = callback(canvas, res.width, res.height, canvasDpr);
          } else if (that.ec) {
            that.initChart(canvas, res.width, res.height, canvasDpr)
          } else {
            that.triggerEvent('init', {
              canvas: canvas,
              width: res.width,
              height: res.height,
              devicePixelRatio: canvasDpr // 增加了dpr，可方便外面echarts.init
            });
          }
        })
        .exec();
    },
    initByNewWay (callback) {
      const that = this
      // version >= 2.9.0：使用新的方式初始化
      const query = wx.createSelectorQuery().in(this);
      query
        .select('.ec-canvas')
        .fields({
          node: true,
          size: true
        })
        .exec(res => {
          const canvasNode = res[0].node;

          const canvasDpr = wx.getSystemInfoSync().pixelRatio;
          const canvasWidth = res[0].width;
          const canvasHeight = res[0].height;

          const ctx = canvasNode.getContext('2d');

          const canvas = new WxCanvas(ctx, that.canvasId, true, canvasNode);
          echarts.setCanvasCreator(() => {
            return canvas;
          });

          if (typeof callback === 'function') {
            that.$curChart = callback(
              canvas,
              canvasWidth,
              canvasHeight,
              canvasDpr
            );
          } else if (that.ec) {
            that.initChart(canvas, canvasWidth, canvasHeight, canvasDpr)
          } else {
            that.triggerEvent('init', {
              canvas: canvas,
              width: canvasWidth,
              height: canvasHeight,
              devicePixelRatio: canvasDpr
            });
          }
        });
    },
    setOption (val) {
      if (!this.$curChart || !this.$curChart.setOption) {
        this.toHandleList.push(val);
      } else {
        this.$curChart.setOption(val);
      }
    },
    canvasToTempFilePath (opt) {
      if (this.isUseNewCanvas) {
        // 新版
        const query = wx.createSelectorQuery().in(this);
        query
          .select('.ec-canvas')
          .fields({
            node: true,
            size: true
          })
          .exec(res => {
            const canvasNode = res[0].node;
            opt.canvas = canvasNode;
            wx.canvasToTempFilePath(opt);
          });
      } else {
        // 旧的
        if (!opt.canvasId) {
          opt.canvasId = this.canvasId;
        }
        ctx.draw(true, () => {
          wx.canvasToTempFilePath(opt, this);
        });
      }
    },

    touchStart (e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault();
        e.stopPropagation();
        return;
      }
      this.$emit('touchstart', e);
      if (this.$curChart && e.touches.length > 0) {
        var touch = e.touches[0];
        var handler = this.$curChart.getZr().handler;
        if (handler) {
          handler.dispatch('mousedown', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'start');
        }
      }
    },

    touchMove (e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault();
        e.stopPropagation();
        return;
      }
      this.$emit('touchmove', e);
      if (this.$curChart && e.touches.length > 0) {
        var touch = e.touches[0];
        var handler = this.$curChart.getZr().handler;
        if (handler) {
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'change');
        }
      }
    },

    touchEnd (e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault();
        e.stopPropagation();
        return;
      }
      this.$emit('touchend', e);
      if (this.$curChart) {
        const touch = e.changedTouches ? e.changedTouches[0] : {};
        var handler = this.$curChart.getZr().handler;
        if (handler) {
          handler.dispatch('mouseup', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.dispatch('click', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'end');
        }
      }
    },

    initChart (canvas, width, height, canvasDpr) {
      this.$curChart = echarts.init(canvas, null, {
        width: width,
        height: height,
        devicePixelRatio: canvasDpr
      });
      this.$curChart.on('click', (param) => {
        if (typeof param.seriesIndex == 'undefined') {
          return;
        }
        if (param.type == 'click') {
          this.$emit('atap', param)
        }
      })
      canvas.setChart(this.$curChart);
      this.$curChart.setOption(this.ec.option);
    }
  }
};
</script>

<style lang="less">
.ec-canvas {
  width: 100%;
  height: 100%;
  display: block;
}
</style>
